package edu.fiu.cis.personalize.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.StringTokenizer;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gwt.user.server.Base64Utils;

import edu.fiu.cis.personalize.shared.User;

@SuppressWarnings("serial")
public class FBAuthentication extends HttpServlet {

	private String appId;
	@SuppressWarnings("unused")
	private String appKey;
	private String redirectURL;
	private String appSecretKey;
	private String scope;

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		appId = config.getInitParameter("APP_ID");
		appKey = config.getInitParameter("APP_KEY");
		appSecretKey = config.getInitParameter("APP_SECRET");
		redirectURL = config.getInitParameter("REDIRECT_URL");
		scope = config.getInitParameter("SCOPE");
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		System.out.println(req.getParameterMap());

		String code = req.getParameter("code");

		User u = null;
		if (code != null) {
			u = _registerByCode(code);
		}

		int uid = u != null ? u.getId() : -1;

		resp.sendRedirect("http://localhost:8888/PersonalizedSearch.html?uid=" + uid);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String signed_request = tryDecodeRequest(req
				.getParameter("signed_request"));

		System.out.println(signed_request);

		String url = "https://www.facebook.com/dialog/oauth?client_id=130157990394331&redirect_uri="
				+ redirectURL + "&scope=" + scope;

		String frame = "<html><head><script> top.location.href='" + url
				+ "'</script></head><body></body></html>";

		resp.getWriter().write(frame);
		resp.getWriter().flush();
		resp.getWriter().close();

	}

	private User _registerByCode(String code) throws IOException {
		String url_format = "https://graph.facebook.com/oauth/access_token?client_id={0}&redirect_uri={1}&client_secret={2}&code={3}";
		URL url = new URL(MessageFormat.format(url_format, appId, redirectURL,
				appSecretKey, code));

		String authStr = null;
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				url.openStream()));
		if (reader.ready()) {
			authStr = reader.readLine();
		}

		HashMap<String, String> authMap = parseAuth(authStr);

		String access_token = authMap.get("access_token");

		if (access_token != null) {
			long expires = Long.parseLong(authMap.get("expires"));

			User u = GraphMediator.registerUser(access_token);

			FBTokenStore.registerToken(u.getId(), access_token, expires);

			return u;
		}

		return null;
	}

	private HashMap<String, String> parseAuth(String authStr) {
		HashMap<String, String> m = new HashMap<String, String>();
		if (authStr != null) {
			StringTokenizer stamp = new StringTokenizer(authStr, "&");
			while (stamp.hasMoreTokens()) {
				String s = stamp.nextToken();
				StringTokenizer st = new StringTokenizer(s, "=");
				if (st.hasMoreTokens()) {
					m.put(st.nextToken(), st.nextToken());
				}
			}
		}
		return m;
	}

	private String tryDecodeRequest(String signed_request) {
		try {
			return new String(Base64Utils.fromBase64(signed_request));
		} catch (Exception e) {
			return null;
		}
	}

}
